//
// Created by yunnan xu on 2020/12/9.
//

#ifndef ANDROIDGRAPHICSDEMOS_BASIC_H
#define ANDROIDGRAPHICSDEMOS_BASIC_H

#include "ext.hpp"
#include <android/log.h>
#include <tuple>
#include <limits>


#define PHYLOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "PhyLib", __VA_ARGS__))
#define PHYLOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, "PhyLib", __VA_ARGS__))
#define PHYLOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, "PhyLib", __VA_ARGS__))

namespace Phy
{

    constexpr float EPS = 1e-6;
    constexpr float PI = 3.1415926;
    constexpr float FLOAT_MAX = std::numeric_limits<float>::max();
    constexpr float FLOAT_MINUS_MAX = -std::numeric_limits<float>::max();

    void LOGMat(const char *, glm::mat4x4);
    void LOGMat(const char *, glm::mat3x3);
    void LOGVec(const char *, glm::vec3);

    class Point
    {
    public:
        Point() = default;
        Point(glm::vec3 p) : pos(p) {}
        glm::vec3 pos;
    };

    class Segment
    {
    public:
        Segment() = default;
        Segment(glm::vec3 p1, glm::vec3 p2) : pos1(p1), pos2(p2){}

        glm::vec3 pos1;
        glm::vec3 pos2;

    };

    class Ray
    {
    public:
        Ray() = default;
        Ray(glm::vec3 p, glm::vec3 d) : pos(p), dir(d) {}

        glm::vec3 pos;
        glm::vec3 dir;
    };

    class Line
    {
    public:

        Line() = default;
        Line(glm::vec3 p, glm::vec3 d) : pos(p), dir(d) {}

        glm::vec3 pos;
        glm::vec3 dir;
    };

    class Plane
    {
    public:

        Plane() = default;
        Plane(glm::vec3 p, glm::vec3 d1, glm::vec3 d2) : pos(p), dir1(d1),  dir2(d2){}

        glm::vec3 pos;
        glm::vec3 dir1;
        glm::vec3 dir2;
    };


    class Triangle
    {
    public:

        Triangle() = default;
        Triangle(glm::vec3 p1, glm::vec3 p2, glm::vec3 p3) : pos1(p1), pos2(p2), pos3(p3){}
        Triangle(Point p1, Point p2, Point p3) : pos1(p1.pos), pos2(p2.pos), pos3(p3.pos){}

        glm::vec3 pos1;
        glm::vec3 pos2;
        glm::vec3 pos3;
    };

    class Tetrahedron
    {
    public:

        Tetrahedron() = default;
        Tetrahedron(glm::vec3 p1, glm::vec3 p2, glm::vec3 p3, glm::vec3 p4)
        {
            pos[0] = p1;
            pos[1] = p2;
            pos[2] = p3;
            pos[3] = p4;
        }

        glm::vec3 pos[4];
    };

    class Sphere
    {
    public:
        glm::vec3 center;
        float radius;
    };

    template<class Shape>
    bool IsPointIn(const Shape & s, const Point & p);


    /*
     *  点到平面的距离
     *
     *  方向向量、距离长度、在那一面
     * */
    std::tuple<glm::vec3, float, bool> Dist(const Plane & s, const Point & p);


    /*
     * 判断p1，p2两个点，是否在Plane的同一侧
     * */
    bool CheckIfTwoPointsInSameSideOfPlane(Point p1, Point p2, Plane plane);

    glm::vec3 CalcNormal(const Triangle & t);
}



#endif //ANDROIDGRAPHICSDEMOS_BASIC_H
